if (addr_is_fr_ip(iface, addr))
continue;
- odhcpd_bitlen2netmask(false, iface->addr4[i].prefix, &mask);
+ odhcpd_bitlen2netmask(false, iface->addr4[i].prefix_len, &mask);
if ((start & ntohl(~mask.s_addr)) == start &&
(end & ntohl(~mask.s_addr)) == end &&
end < ntohl(~mask.s_addr)) { /* Exclude broadcast address */
}
/* Don't allocate IP range for subnets smaller than /28 */
- if (iface->addr4[0].prefix > MAX_PREFIX_LEN) {
+ if (iface->addr4[0].prefix_len > MAX_PREFIX_LEN) {
warn("Auto allocation of DHCP range fails on %s (prefix length must be < %d).",
iface->name, MAX_PREFIX_LEN + 1);
return -1;
iface->dhcpv4_local = iface->addr4[0].addr.in;
iface->dhcpv4_bcast = iface->addr4[0].broadcast;
- odhcpd_bitlen2netmask(false, iface->addr4[0].prefix, &iface->dhcpv4_mask);
+ odhcpd_bitlen2netmask(false, iface->addr4[0].prefix_len, &iface->dhcpv4_mask);
end = start = iface->dhcpv4_local.s_addr & iface->dhcpv4_mask.s_addr;
/* Auto allocate ranges */
memset(&ip, 0, sizeof(ip));
ip.addr.in = iface->dhcpv4_local;
- ip.prefix = odhcpd_netmask2bitlen(false, &iface->dhcpv4_mask);
+ ip.prefix_len = odhcpd_netmask2bitlen(false, &iface->dhcpv4_mask);
ip.broadcast = iface->dhcpv4_bcast;
dhcpv4_setup_addresses(iface);
struct in6_addr in6_from_prefix_and_iid(const struct odhcpd_ipaddr *prefix, uint64_t iid)
{
struct in6_addr addr;
- uint8_t iid_len = min(128 - prefix->prefix, 64);
+ uint8_t iid_len = min(128 - prefix->prefix_len, 64);
addr = prefix->addr.in6;
in6_copy_iid(&addr, iid, iid_len);
continue;
if (addr->preferred_lt > (uint32_t)now &&
- addr->prefix < 64 &&
- addr->prefix > minprefix)
- minprefix = addr->prefix;
+ addr->prefix_len < 64 &&
+ addr->prefix_len > minprefix)
+ minprefix = addr->prefix_len;
}
if (minprefix > 32 && minprefix <= 64)
.len = htons(sizeof(o_ia_p) - 4),
.preferred_lt = htonl(prefix_preferred_lt),
.valid_lt = htonl(prefix_valid_lt),
- .prefix = a->length,
+ .prefix_len = a->length,
.addr = addrs[i].addr.in6,
};
o_ia_p.addr.s6_addr32[1] |= htonl(a->assigned_subnet_id);
o_ia_p.addr.s6_addr32[2] = o_ia_p.addr.s6_addr32[3] = 0;
- if (!valid_prefix_length(a, addrs[i].prefix))
+ if (!valid_prefix_length(a, addrs[i].prefix_len))
continue;
if (buflen < ia_len + sizeof(o_ia_p))
if (!valid_addr(&addrs[i], now))
continue;
- if (!valid_prefix_length(a, addrs[i].prefix))
+ if (!valid_prefix_length(a, addrs[i].prefix_len))
continue;
if (ADDR_MATCH_PIO_FILTER(&addrs[i], iface))
addr.s6_addr32[2] = addr.s6_addr32[3] = 0;
if (!memcmp(&ia_p->addr, &addr, sizeof(addr)) &&
- ia_p->prefix == a->length)
+ ia_p->prefix_len == a->length)
found = true;
} else {
addr = in6_from_prefix_and_iid(&addrs[i], a->assigned_host_id);
.len = htons(sizeof(o_ia_p) - 4),
.preferred_lt = 0,
.valid_lt = 0,
- .prefix = ia_p->prefix,
+ .prefix_len = ia_p->prefix_len,
.addr = ia_p->addr,
};
continue;
if (ia->type == htons(DHCPV6_OPT_IA_PD)) {
- if (p->prefix < addrs[i].prefix ||
- odhcpd_bmemcmp(&p->addr, &addrs[i].addr.in6, addrs[i].prefix))
+ if (p->prefix_len < addrs[i].prefix_len ||
+ odhcpd_bmemcmp(&p->addr, &addrs[i].addr.in6, addrs[i].prefix_len))
continue;
- } else if (odhcpd_bmemcmp(&n->addr, &addrs[i].addr.in6, addrs[i].prefix))
+ } else if (odhcpd_bmemcmp(&n->addr, &addrs[i].addr.in6, addrs[i].prefix_len))
continue;
onlink = true;
continue;
struct dhcpv6_ia_prefix *p = (struct dhcpv6_ia_prefix*)&sdata[-4];
- if (p->prefix) {
- reqlen = p->prefix;
+ if (p->prefix_len) {
+ reqlen = p->prefix_len;
reqhint = ntohl(p->addr.s6_addr32[1]);
if (reqlen > 32 && reqlen <= 64)
reqhint &= (1U << (64 - reqlen)) - 1;
#define ADDR_ENTRY_VALID_IA_ADDR(iface, i, m, addrs) \
((iface)->dhcpv6_assignall || \
(i) == (m) || \
- (addrs)[(i)].prefix > 64)
+ (addrs)[(i)].prefix_len > 64)
size_t get_preferred_addr(const struct odhcpd_ipaddr *addrs, const size_t addrlen);
static inline bool valid_addr(const struct odhcpd_ipaddr *addr, time_t now)
{
- return (addr->prefix <= 96 && addr->valid_lt > (uint32_t)now && addr->preferred_lt > (uint32_t)now);
+ return (addr->prefix_len <= 96 && addr->valid_lt > (uint32_t)now && addr->preferred_lt > (uint32_t)now);
}
#endif /* _DHCPV6_IA_H_ */
uint16_t len;
uint32_t preferred_lt;
uint32_t valid_lt;
- uint8_t prefix;
+ uint8_t prefix_len;
struct in6_addr addr;
} _o_packed;
change = len != (ssize_t)iface->addr6_len;
for (ssize_t i = 0; !change && i < len; ++i) {
if (!IN6_ARE_ADDR_EQUAL(&addr[i].addr.in6, &iface->addr6[i].addr.in6) ||
- addr[i].prefix != iface->addr6[i].prefix ||
+ addr[i].prefix_len != iface->addr6[i].prefix_len ||
(addr[i].preferred_lt > (uint32_t)now) != (iface->addr6[i].preferred_lt > (uint32_t)now) ||
addr[i].valid_lt < iface->addr6[i].valid_lt || addr[i].preferred_lt < iface->addr6[i].preferred_lt)
change = true;
return NL_SKIP;
memset(&addrs[ctxt->ret], 0, sizeof(addrs[ctxt->ret]));
- addrs[ctxt->ret].prefix = ifa->ifa_prefixlen;
+ addrs[ctxt->ret].prefix_len = ifa->ifa_prefixlen;
nla_memcpy(&addrs[ctxt->ret].addr, nla_addr,
sizeof(addrs[ctxt->ret].addr));
static int prefix_cmp(const void *va, const void *vb)
{
const struct odhcpd_ipaddr *a = va, *b = vb;
- int ret = 0;
- if (a->prefix == b->prefix) {
- ret = (ntohl(a->addr.in.s_addr) < ntohl(b->addr.in.s_addr)) ? 1 :
- (ntohl(a->addr.in.s_addr) > ntohl(b->addr.in.s_addr)) ? -1 : 0;
- } else
- ret = a->prefix < b->prefix ? 1 : -1;
+ if (a->prefix_len != b->prefix_len)
+ return a->prefix_len < b->prefix_len ? 1 : -1;
- return ret;
+ if (ntohl(a->addr.in.s_addr) == ntohl(b->addr.in.s_addr))
+ return 0;
+
+ return ntohl(a->addr.in.s_addr) < ntohl(b->addr.in.s_addr) ? 1 : -1;
}
struct nl_msg *msg;
struct ifaddrmsg ifa = {
.ifa_family = v6 ? AF_INET6 : AF_INET,
- .ifa_prefixlen = addr->prefix,
+ .ifa_prefixlen = addr->prefix_len,
.ifa_flags = 0,
.ifa_scope = 0,
.ifa_index = ifindex, };
addr = in6_from_prefix_and_iid(&addrs[i], lease->assigned_host_id);
} else {
- if (!valid_prefix_length(lease, addrs[i].prefix))
+ if (!valid_prefix_length(lease, addrs[i].prefix_len))
continue;
addr = addrs[i].addr.in6;
#define ADDR_MATCH_PIO_FILTER(_addr, iface) (odhcpd_bmemcmp(&(_addr)->addr, \
&(iface)->pio_filter_addr, \
(iface)->pio_filter_length) != 0 || \
- (_addr)->prefix < (iface)->pio_filter_length)
+ (_addr)->prefix_len < (iface)->pio_filter_length)
struct interface;
struct nl_sock;
struct odhcpd_ipaddr {
union in46_addr addr;
- uint8_t prefix;
+ uint8_t prefix_len;
uint32_t preferred_lt;
uint32_t valid_lt;
union {
/* ipv6 only */
struct {
- uint8_t dprefix;
+ uint8_t dprefix_len;
bool tentative;
};
/* Detect whether a default route exists, also find the source prefixes */
static bool parse_routes(struct odhcpd_ipaddr *n, ssize_t len)
{
- struct odhcpd_ipaddr p = { .addr.in6 = IN6ADDR_ANY_INIT, .prefix = 0,
- .dprefix = 0, .preferred_lt = 0, .valid_lt = 0};
+ struct odhcpd_ipaddr p = {
+ .addr.in6 = IN6ADDR_ANY_INIT,
+ .prefix_len = 0,
+ .dprefix_len = 0,
+ .preferred_lt = 0,
+ .valid_lt = 0
+ };
bool found_default = false;
char line[512], ifname[16];
found_default = true;
} else if (sscanf(line, "%8" SCNx32 "%8" SCNx32 "%*8" SCNx32 "%*8" SCNx32 " %hhx %*s "
"%*s 00000000000000000000000000000000 %*s %*s %*s %" SCNx32 " lo",
- &p.addr.in6.s6_addr32[0], &p.addr.in6.s6_addr32[1], &p.prefix, &rflags) &&
- p.prefix > 0 && (rflags & RTF_NONEXTHOP) && (rflags & RTF_REJECT)) {
+ &p.addr.in6.s6_addr32[0], &p.addr.in6.s6_addr32[1], &p.prefix_len, &rflags) &&
+ p.prefix_len > 0 && (rflags & RTF_NONEXTHOP) && (rflags & RTF_REJECT)) {
// Find source prefixes by scanning through unreachable-routes
p.addr.in6.s6_addr32[0] = htonl(p.addr.in6.s6_addr32[0]);
p.addr.in6.s6_addr32[1] = htonl(p.addr.in6.s6_addr32[1]);
for (ssize_t i = 0; i < len; ++i) {
- if (n[i].prefix <= 64 && n[i].prefix >= p.prefix &&
- !odhcpd_bmemcmp(&p.addr.in6, &n[i].addr.in6, p.prefix)) {
- n[i].dprefix = p.prefix;
+ if (n[i].prefix_len <= 64 && n[i].prefix_len >= p.prefix_len &&
+ !odhcpd_bmemcmp(&p.addr.in6, &n[i].addr.in6, p.prefix_len)) {
+ n[i].dprefix_len = p.prefix_len;
break;
}
}
struct nd_opt_route_info {
uint8_t type;
uint8_t len;
- uint8_t prefix;
+ uint8_t prefix_len;
uint8_t flags;
uint32_t lifetime;
uint32_t addr[4];
for (size_t i = 0; i < iface->pio_cnt; i++) {
struct ra_pio *cur_pio = &iface->pios[i];
- if (addr->prefix == cur_pio->length &&
- !odhcpd_bmemcmp(&addr->addr.in6, &cur_pio->prefix, cur_pio->length))
+ if (addr->prefix_len == cur_pio->length &&
+ !odhcpd_bmemcmp(&addr->addr.in6, &cur_pio->prefix, cur_pio->length))
return cur_pio;
}
iface->pio_cnt++;
memcpy(&pio->prefix, &addr->addr.in6, sizeof(pio->prefix));
- pio->length = addr->prefix;
+ pio->length = addr->prefix_len;
pio->lifetime = 0;
iface->pio_update = true;
for (size_t j = 0; j < valid_addr_cnt; j++) {
struct odhcpd_ipaddr *cur_addr = &addrs[j];
- if (cur_pio->length == cur_addr->prefix &&
- !odhcpd_bmemcmp(&cur_pio->prefix, &cur_addr->addr.in6, cur_pio->length)) {
+ if (cur_pio->length == cur_addr->prefix_len &&
+ !odhcpd_bmemcmp(&cur_pio->prefix, &cur_addr->addr.in6, cur_pio->length)) {
pio_found = true;
break;
}
struct odhcpd_ipaddr *addr = &addrs[total_addr_cnt];
memcpy(&addr->addr.in6, &cur_pio->prefix, sizeof(addr->addr.in6));
- addr->prefix = cur_pio->length;
+ addr->prefix_len = cur_pio->length;
addr->preferred_lt = 0;
addr->valid_lt = (uint32_t) (now + ND_VALID_LIMIT);
total_addr_cnt++;
uint32_t preferred_lt = 0;
uint32_t valid_lt = 0;
- if (addr->prefix > 96 || (i < valid_addr_cnt && addr->valid_lt <= (uint32_t)now)) {
+ if (addr->prefix_len > 96 || (i < valid_addr_cnt && addr->valid_lt <= (uint32_t)now)) {
info("Address %s (prefix %d, valid-lifetime %u) not suitable as RA prefix on %s",
- inet_ntop(AF_INET6, &addr->addr.in6, buf, sizeof(buf)), addr->prefix,
+ inet_ntop(AF_INET6, &addr->addr.in6, buf, sizeof(buf)), addr->prefix_len,
addr->valid_lt, iface->name);
continue;
}
}
for (size_t i = 0; i < pfxs_cnt; ++i) {
- if (addr->prefix == pfxs[i].nd_opt_pi_prefix_len &&
- !odhcpd_bmemcmp(&pfxs[i].nd_opt_pi_prefix,
- &addr->addr.in6, addr->prefix))
+ if (addr->prefix_len == pfxs[i].nd_opt_pi_prefix_len &&
+ !odhcpd_bmemcmp(&pfxs[i].nd_opt_pi_prefix,
+ &addr->addr.in6, addr->prefix_len))
p = &pfxs[i];
}
}
odhcpd_bmemcpy(&p->nd_opt_pi_prefix, &addr->addr.in6,
- (iface->ra_advrouter) ? 128 : addr->prefix);
+ (iface->ra_advrouter) ? 128 : addr->prefix_len);
p->nd_opt_pi_type = ND_OPT_PREFIX_INFORMATION;
p->nd_opt_pi_len = 4;
- p->nd_opt_pi_prefix_len = (addr->prefix < 64) ? 64 : addr->prefix;
+ p->nd_opt_pi_prefix_len = (addr->prefix_len < 64) ? 64 : addr->prefix_len;
/* RFC9762 DHCPv6-PD Preferred Flag § 6:
* Routers SHOULD set the P flag to zero by default...
*/
p->nd_opt_pi_flags_reserved = 0;
if (!iface->ra_not_onlink)
p->nd_opt_pi_flags_reserved |= ND_OPT_PI_FLAG_ONLINK;
- if (iface->ra_slaac && addr->prefix <= 64)
+ if (iface->ra_slaac && addr->prefix_len <= 64)
p->nd_opt_pi_flags_reserved |= ND_OPT_PI_FLAG_AUTO;
if (iface->dhcpv6 != MODE_DISABLED && iface->dhcpv6_pd && iface->dhcpv6_pd_preferred)
/* RFC9762 DHCPv6-PD Preferred Flag
struct nd_opt_route_info *tmp;
uint32_t valid_lt;
- if (addr->dprefix >= 64 || addr->dprefix == 0 || addr->valid_lt <= (uint32_t)now) {
+ if (addr->dprefix_len >= 64 || addr->dprefix_len == 0 || addr->valid_lt <= (uint32_t)now) {
info("Address %s (dprefix %d, valid-lifetime %u) not suitable as RA route on %s",
inet_ntop(AF_INET6, &addr->addr.in6, buf, sizeof(buf)),
- addr->dprefix, addr->valid_lt, iface->name);
+ addr->dprefix_len, addr->valid_lt, iface->name);
continue; /* Address not suitable */
}
continue; /* PIO filtered out of this RA */
}
- if (addr->dprefix > 32) {
- addr->addr.in6.s6_addr32[1] &= htonl(~((1U << (64 - addr->dprefix)) - 1));
- } else if (addr->dprefix <= 32) {
- addr->addr.in6.s6_addr32[0] &= htonl(~((1U << (32 - addr->dprefix)) - 1));
+ if (addr->dprefix_len > 32) {
+ addr->addr.in6.s6_addr32[1] &= htonl(~((1U << (64 - addr->dprefix_len)) - 1));
+ } else if (addr->dprefix_len <= 32) {
+ addr->addr.in6.s6_addr32[0] &= htonl(~((1U << (32 - addr->dprefix_len)) - 1));
addr->addr.in6.s6_addr32[1] = 0;
}
memset(&routes[routes_cnt], 0, sizeof(*routes));
routes[routes_cnt].type = ND_OPT_ROUTE_INFO;
routes[routes_cnt].len = sizeof(*routes) / 8;
- routes[routes_cnt].prefix = addr->dprefix;
+ routes[routes_cnt].prefix_len = addr->dprefix_len;
routes[routes_cnt].flags = 0;
if (iface->route_preference < 0)
routes[routes_cnt].flags |= ND_RA_PREF_LOW;